﻿using System;
using System.Text;

using System.Collections.Generic;

using SilverlightCairngorm.Command;

namespace SilverlightCairngorm.Control
{
    /// <summary>
    /// The system controller's parent, implementing the event-command
    /// relationship inner-workings, using a dictionary relating
    /// event names to commands.
    /// 
    /// subscribes to the EventDispatched event of the CairngormEventDispatcher
    /// to handle all system events.
    /// </summary>
    public abstract class FrontController
    {
        /// <summary>
        /// The dictionary of eventNames and corresponding commands to be executed
        /// </summary>
        private Dictionary<string, Type> eventMap = new Dictionary<string, Type>();

        public FrontController()
        {
			CairngormEventDispatcher.Instance.EventDispatched +=
				new CairngormEventDispatcher.EventDispatchDelegate(ExecuteCommand);
        }

        /// <summary>
        /// Whenever the CairngormEventDispatcher raises an event, this
        /// method gets the CairngormEvent inside it - and calls
        /// the execute() method on the corresponding ICommand
        /// </summary>
        /// <param name="sender">Unused</param>
		/// <param name="args">The CairngormEventArgs containing an instance of the raised CairngormEvent</param>
		void ExecuteCommand(object sender, CairngormEventArgs args)
        {
            if (eventMap.ContainsKey(args.raisedEvent.Name))
            {
                ICommand cmdInstance = Activator.CreateInstance(eventMap[args.raisedEvent.Name]) as ICommand;
				cmdInstance.execute(args.raisedEvent);
            }
        }

        /// <summary>
        /// register a Cairngorm event to FrontController
        /// </summary>
        /// <param name="cairngormEventName"></param>
        /// <param name="command"></param>
        public void addCommand(string cairngormEventName, Type commandType)
        {
			//one command type can only register once
			if (eventMap.ContainsKey(cairngormEventName))
				throw new CairngormError(CairngormMessageCodes.COMMAND_ALREADY_REGISTERED, cairngormEventName);
			//the command type MUST implement ICommand interface
			if (!(typeof(ICommand).IsAssignableFrom(commandType)))
				throw new CairngormError(CairngormMessageCodes.COMMAND_NOT_IMPLEMENT_ICOMMAND, cairngormEventName);

			eventMap.Add(cairngormEventName, commandType);
        }

		public void removeCommand(string commandName) 
		{
			if (eventMap.ContainsKey(commandName))
				eventMap.Remove(commandName);
		}

    }
}
